/*******************************************************************************
 *   Copyright (c) 2010~2018 charles
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 *  created at 2018-09-03 11:02:49
 ******************************************************************************/

package libgin

import (
	"errors"
	"fmt"
	"mime/multipart"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/gin-gonic/gin"

	"gitee.com/goframe/lt-collector/libs/abio"
)

const (
	_        = iota
	KB int64 = 1 << (10 * iota)
	MB
	GB
	TB

	fileMaxSize = KB * 500
	PathName    = "upload"
)

var Upload = new(up)

type (
	up struct {
		mu sync.Mutex
		fh *multipart.FileHeader
	}
)

func (u *up) hasImageExt(fileName string) bool {
	extensionNames := []string{"png", "jpg", "gif", "jpeg"}
	ext := strings.Replace(filepath.Ext(fileName), ".", "", -1)
	for _, val := range extensionNames {
		if val == ext {
			return true
		}
	}
	return false
}

//检测重名文件,并获取新的文件名
func (u *up) noCoverFileName(ph string) string {
	var fileName string
	filePathStr := filepath.Join(abio.SelfDir(), ph, u.fh.Filename)
	if abio.FileExists(filePathStr) {
		ext := filepath.Ext(u.fh.Filename)
		fileName = time.Now().Format("20060102150405") + "_" +
			strings.Replace(u.fh.Filename, ext, "", -1) + "_" +
			fmt.Sprintf("%d", time.Now().Unix()) + ext
	} else {
		fileName = u.fh.Filename
	}
	return fileName
}

func (u *up) Do(c *gin.Context) {
	if err := u.do(c); err != nil {
		_ = c.Error(err)
	}
}

func (u *up) do(c *gin.Context) (err error) {
	u.mu.Lock()
	defer u.mu.Unlock()
	var (
		cover       = false
		limitSize   = true
		newFileName string
		clPath      string
	)
	savePathName := c.PostForm("root")
	if len(savePathName) == 0 {
		savePathName = PathName
	}
	clPath = filepath.Join(savePathName, c.PostForm("path"))
	coverQuery := c.Query("cover")
	if coverQuery != "" {
		cover, _ = strconv.ParseBool(coverQuery)
	}
	limitQuery := c.Query("limit_size")
	if limitQuery != "" {
		limitSize, _ = strconv.ParseBool(limitQuery)
	}
	if u.fh, err = c.FormFile("file"); err != nil {
		return
	}
	fh := u.fh
	if !u.hasImageExt(fh.Filename) && limitSize {
		return errors.New("文件错误")
	}
	if fh.Size > fileMaxSize && limitSize {
		return errors.New("文件大小超出限制:" + fmt.Sprintf("%dKB", fileMaxSize/KB))
	}
	if cover {
		newFileName = u.fh.Filename
	} else {
		newFileName = u.noCoverFileName(clPath)
	}
	pFileName := filepath.Join(abio.SelfDir(), clPath, newFileName)
	if err = abio.TouchFile(pFileName); err != nil {
		return
	}
	if err = c.SaveUploadedFile(fh, pFileName); err != nil {
		return
	}
	rst := filepath.Join("/", clPath, newFileName)
	Return.GinOK(c, rst)
	return
}
